
/**
 *  \file GA_bearer_api.h
 *
 *  \brief This file defines the GA bearer Interface - includes
 *  Data Structures and Methods.
 */

/*
 *  Copyright (C) 2020. Mindtree Ltd.
 *  All rights reserved.
 */

#ifndef _H_GA_BEARER_API_
#define _H_GA_BEARER_API_


/* --------------------------------------------- Header File Inclusion */
#include "EM_os.h"
#include "EM_debug.h"

/* --------------------------------------------- Global Definitions */
/* Unreferenced variable macro to avoid compilation warnings */
#define GA_IGNORE_UNUSED_PARAM(v) (void)(v)

/* Bearer Error Code */
#define GA_BRR_INVALID_STATE                        0x1011
#define GA_BRR_INVALID_PARAMS                       0x1012

/** GA Basic return values */
#define GA_SUCCESS                                  0x0000
#define GA_FAILURE                                  0xFFFF
#define GA_EVT_CONSUMED                             0x8000

/** Boolean values */
#define GA_TRUE                                     0x01
#define GA_FALSE                                    0x00

#define GA_BRR_PROFILE_ID_INVALID                   0xFF
#define GA_BRR_SERVICE_ID_INVALID                   0xFF
#define GA_BRR_SERVICE_TYPE_INVALID                 0xFF
#define GA_BRR_UUID_INVALID                         0x0000

/** Continuation state of events */
#define GA_CONTINUE                                 0x00C0

/** Device Address size */
#define GA_BD_ADDR_SIZE                             6

/** Dont care Service and Characteristic instance */
#define GA_BRR_INST_DONTCARE                        0xFF

/** Events from Bearer to GA Core/Profiles */
#define GA_BRR_SETUP_TRANSPORT_CNF                  0x00
#define GA_BRR_DISCOVER_SERVICE_CNF                 0x01
#define GA_BRR_GET_SERVICE_COMPOSITION_CNF          0x02

#define GA_BRR_WRITE_CHARACTERISTIC_CNF             0x03
#define GA_BRR_READ_CHARACTERISTIC_CNF              0x04
#define GA_BRR_CONFIG_CHARACTERISTIC_CNF            0x05
#define GA_BRR_NOTIFICATION_IND                     0x06

#define GA_BRR_SETUP_TRANSPORT_IND                  0x10
#define GA_BRR_WRITE_CHARACTERISTIC_IND             0x11
#define GA_BRR_READ_CHARACTERISTIC_IND              0x12
#define GA_BRR_CONFIG_CHARACTERISTIC_IND            0x13

#define GA_BRR_TRANSPORT_UP_IND                     0x81
#define GA_BRR_TRANSPORT_DOWN_IND                   0x82

#define GA_BRR_EVENT_INVALID                        0xFF


/**
 * Bearer Internal Roles, used to identify modes of interaction
 * with upper layer.
 */
#define GA_BRR_GENERIC_ROLE                         0x00
#define GA_BRR_PROFILE_ROLE                         0x01
#define GA_BRR_SERVICE_ROLE                         0x02
#define GA_BRR_INVALID_ROLE                         0xFF

/**
 * TODO: Need events for Transport Disconnection too?
 * Currently looks like the Idea was to have
 * - GA_BRR_SETUP_TRANSPORT_CNF for Profile roles
 * - GA_BRR_SETUP_TRANSPORT_IND for Server roles
 * Need to check if these events are to be unified and
 * provided to GA profile and service callbacks or
 * provided only to GA Core Callback.
 */

/* --------------------------------------------- Data types /Structures */

/** GA Result type */
typedef UINT16 GA_RESULT;

/** GA Bearer Device Indentifier */
/* TODO: Reference to Endpoint in GA core */
typedef struct _GA_BRR_DEVICE
{
    /** Bluetooth Device Address */
    UCHAR bd_addr[GA_BD_ADDR_SIZE];

    /** Bluetooth Device Type */
    UINT8 bd_type;

} GA_BRR_DEVICE;

/** GA Bearer Profile Handle */
typedef UINT8 GA_BRR_PRF_HANDLE;

/** GA Bearer Characteristic Handle */
typedef UINT16 GA_BRR_CHR_HANDLE;

/** GA Bearer Service Instance */
typedef UINT8 GA_BRR_SVC_INST;

/** GA Bearer Characteristic Instance */
typedef UINT8 GA_BRR_CHR_INST;

/** GA Bearer UUID type */
/* TODO: <- Make provision for 128bit? */
typedef UINT16 GA_BRR_UUID;

/** GA Bearer Characteristic Context localy */
typedef struct _GA_BRR_CHR_CONTEXT
{
    /** UUID of Characteristic */
    GA_BRR_UUID uuid;

    /** Characteristic Instance */
    GA_BRR_CHR_INST inst;

    /** is response required */
    UINT8 to_rsp;

} GA_BRR_CHR_CONTEXT;

/** GA Bearer Characteristic Value */
typedef struct _GA_BRR_CHR_VAL
{
    /** Value array of octets */
    UCHAR * val;

    /** Value length */
    UINT16 len;

} GA_BRR_CHR_VAL;

/** GA Bearer Service Range */
typedef struct _GA_BRR_SVC_RANGE
{
    /* Start of Service */
    UINT16 start;

    /* End of Service */
    UINT16 end;

} GA_BRR_SVC_RANGE;

/** Service UUID information - Will be a list of this as event_data in GA_BRR_DISCOVER_SERVICE_CNF */
typedef struct _GA_BRR_SVC_INFO
{
    /** UUID of the service */
    GA_BRR_UUID uuid;

    /** Service Range */
    GA_BRR_SVC_RANGE range;

} GA_BRR_SVC_INFO;

/** Characteristic UUID information */
typedef struct _GA_BRR_CHR_INFO
{
    /** UUID of the characteristic */
    GA_BRR_UUID uuid;

    /** Characteristic Handle */
    UINT16 handle;

    /** Characteristic Property */
    UINT8 property;

    /**
     * TODO:
     * Check if we need to maintain Descriptor/CCCD Handle.
     * Is CCCD Always (Value Handle + 1)?
     */

} GA_BRR_CHR_INFO;

/** Service Composition Data - Will be the event_data in GA_BRR_GET_SERVICE_COMPOSITION_CNF */
typedef struct _GA_BRR_SERVICE_COMPOSITION
{
    /** Service Information */
    GA_BRR_SVC_INFO * service;

    /** List of Characteristic Information */
    GA_BRR_CHR_INFO * characteristic;

    /** Number of Characteristics */
    UINT8 characteristic_count;

} GA_BRR_SERVICE_COMPOSITION;

/** GA Bearer Callback to core */
typedef GA_RESULT (* GA_BRR_CB)
                  (
                      /* IN */ GA_BRR_DEVICE * device,
                      /* IN */ UINT8 event_type,
                      /* IN */ UINT16 event_status,
                      /* IN */ void * event_data,
                      /* IN */ UINT16 event_datalen
                  );

/** GA Profile Callback to the core */
/**
 * Bearer Callback to Profile?
 */
typedef GA_RESULT (* GA_BRR_PROFILE_CB)
                  (
                      /* IN */ GA_BRR_DEVICE * device,
                      /* IN */ void          * context,
                      /* IN */ UINT8         event_type,
                      /* IN */ UINT16        event_status,
                      /* IN */ void          * event_data,
                      /* IN */ UINT16        event_datalen
                   );

/** GA Service Callback to the core  */
/**
 * Bearer Callback to a Given Service?
 */
typedef GA_RESULT (* GA_BRR_SERVICE_CB)
                  (
                      /* IN */ GA_BRR_DEVICE * device,
                      /* IN */ void          * context,
                      /* IN */ UINT8         event_type,
                      /* IN */ UINT16        event_status,
                      /* IN */ void          * event_data,
                      /* IN */ UINT16        event_datalen
                   );

/* Call Back to Inform GA BRR Internal layer from GA BRR Platform Abstraction */
typedef GA_RESULT (* GA_BRR_PL_CB)
                  (
                      /* IN */ GA_BRR_DEVICE * device,
                      /* IN */ void          * context,
                      /* IN */ UCHAR         brr_role,
                      /* IN */ void          * inst_handle,
                      /* IN */ UINT8         event_type,
                      /* IN */ UINT16        event_status,
                      /* IN */ void          * event_data,
                      /* IN */ UINT16        event_datalen
                   );

/** Interface structure for all bearer procedures */
typedef struct _GA_BRR_INTERFACE
{
    /**
     *  \brief To Init the GA Bearer Layer.
     *
     *  \par Description:
     *       This function enables to inilialize the GA Bearer Layer.
     *
     *  \param [in] cb
     *         Common callback of GA core
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* init) (GA_BRR_CB);

    /**
     *  \brief To Shutdown the GA Bearer Layer.
     *
     *  \par Description:
     *       This function enables to shutdown the GA Bearer Layer.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* shutdown) (void);

    /**
     *  \brief Add a GATT Service.
     *
     *  \par Description:
     *       This function enables to add a GATT Service with the GA Bearer.
     *
     *  \param [in] service_uuid
     *         Assigned UUID of this GATT Service.
     *
     *  \param [in] service_type
     *         Type associated with the service.
     *
     *  \param [in] cb
     *         Callback associated with Service ID.
     *
     *  \param [out] sid
     *         Service context ID.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* add_service) (GA_BRR_UUID, UINT8, GA_BRR_SERVICE_CB, GA_BRR_SVC_INST *);

    /**
     *  \brief Add a Included GATT Service.
     *
     *  \par Description:
     *       This function enables to add a Included GATT Service with the
     *       GA Bearer.
     *
     *  \param [in] sid
     *         Service context ID.
     *
     *  \param [in] service_uuid
     *         Assigned UUID of this GATT Service.
     *
     *  \param [out] isid
     *         Included Service context ID.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* include_service) (GA_BRR_SVC_INST, GA_BRR_UUID, GA_BRR_SVC_INST *);

    /**
     *  \brief Remove a GATT Service.
     *
     *  \par Description:
     *       This function enables to remove a GATT Service with the GA Bearer.
     *
     *  \param [in] sid
     *         Service context ID.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* remove_service) (GA_BRR_SVC_INST);

    /**
     *  \brief Add a GATT Characteristic to a Service.
     *
     *  \par Description:
     *       This function enables to add a GATT Characteristic to a given
     *       Service with the GA Bearer.
     *
     *  \param [in] sid
     *         Service context ID.
     *
     *  \param [in] char_uuid
     *         Assigned UUID of this GATT Characteristic.
     *
     *  \param [in] char_property
     *         Properties associated with this GATT Characteristic.
     *
     *  \param [in] value
     *         Any value associated with this GATT Characteristic.
     *
     *  \param [out] cid
     *         Characteristic context ID.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* add_characteristic) (GA_BRR_SVC_INST, GA_BRR_UUID, UINT8, GA_BRR_CHR_VAL *, GA_BRR_CHR_INST *);

    /**
     * Provision to update the characteric value
     */
    /**
     *  \brief Update a GATT Characteristic to a Service.
     *
     *  \par Description:
     *       This function enables to Update a GATT Characteristic to a given
     *       Service with the GA Bearer.
     *
     *  \param [in] sid
     *         Service context ID.
     *
     *  \param [in] char_uuid
     *         Assigned UUID of this GATT Characteristic.
     *
     *  \param [in] cid
     *         Characteristic context ID.
     *
     *  \param [in] value
     *         Any value associated with this GATT Characteristic.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* update_characteristic_value) (GA_BRR_SVC_INST, GA_BRR_UUID, GA_BRR_CHR_INST, GA_BRR_CHR_VAL *);

    /**
     *  \brief Send response for a Characterisitc Write.
     *
     *  \par Description:
     *       This function enables to respond to a Characteritis Write
     *       from a peer device.
     *
     *  \param [in] device
     *         Peer Device Connection Identifier.
     *
     *  \param [in] ctx
     *         Assigned UUID of this GATT Characteristic.
     *
     *  \param [in] status
     *         Characteristic context ID.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* write_characteristic_rsp) (GA_BRR_DEVICE *, GA_BRR_CHR_CONTEXT *, UINT16);

    /**
     *  \brief Send response for a Characterisitc Read.
     *
     *  \par Description:
     *       This function enables to respond to a Characteritis Read
     *       from a peer device.
     *
     *  \param [in] device
     *         Peer Device Connection Identifier.
     *
     *  \param [in] ctx
     *         Assigned UUID of this GATT Characteristic.
     *
     *  \param [in] status
     *         Characteristic context ID.
     *
     *  \param [in] value
     *         Any value associated with this GATT Characteristic.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* read_characteristic_rsp) (GA_BRR_DEVICE *, GA_BRR_CHR_CONTEXT *, UINT16, GA_BRR_CHR_VAL *);

    /** Notify/Indicate value of the specified characteristic UUID for the peer device */
    /**
     *  \brief Notify a Characterisitic Value to peer device.
     *
     *  \par Description:
     *       This function enables to send a charactertisic Notifications to
     *       peer device.
     *
     *  \param [in] device
     *         Peer Device Connection Identifier.
     *
     *  \param [in] sid
     *         Service context ID.
     *
     *  \param [in] char_uuid
     *         Assigned UUID of this GATT Characteristic.
     *
     *  \param [in] cid
     *         Characteristic context ID where needed, else can be
     *         \ref GA_BRR_INST_DONTCARE.
     *
     *  \param [in] value
     *         Any value associated with this GATT Characteristic.
     *
     *  \param [in] nwr
     *         TODO: Check what this is!
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* notify_characteristic) (GA_BRR_DEVICE *, GA_BRR_SVC_INST, GA_BRR_UUID, GA_BRR_CHR_INST, GA_BRR_CHR_VAL *, UINT8);

    /**
     * Register a profile callback from GA and assign a profile ID for further
     * referencing.
     * Assign a profile ID or Profile ID gets assigned internally and comes
     * as Out?
     */
    /**
     *  \brief Register a profile client/collector.
     *
     *  \par Description:
     *       This function enables to Register a profile client/collector module
     *       with the GA Bearer.
     *
     *  \param [in] cb
     *         Profile Callback.
     *
     *  \param [out] pid
     *         Profile context ID.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* register_profile) (GA_BRR_PROFILE_CB, GA_BRR_PRF_HANDLE *);

    /**
     *  \brief To Unregister a GA Profile with GA Bearer.
     *
     *  \par Description:
     *       This function enables to unregister a profile with GA Bearer.
     *
     *  \param [in] pid
     *         Profile context ID.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* unregister_profile) (GA_BRR_PRF_HANDLE);


    /**
     * Enhance the bearer transport if required by the profile or application - eATT
     * Should the needed MTU(or other associated things incase of eATT) also be
     * part of this interface? Else, we might need some other interface for that.
     */
    /**
     *  \brief Update or Setup a new Transport.
     *
     *  \par Description:
     *       TODO: Need to revist for both Profile and Server roles.
     *
     *  \param [in] pid
     *         Profile context ID.
     *
     *  \param [in] type
     *         Type of Transport.
     *
     *  \param [in] enable
     *         State of Transport.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* setup_transport) (GA_BRR_PRF_HANDLE, UINT8, UINT8);

    /**
     * Discover the service information from a profile instance for a service from
     * the peer device.
     */
    /**
     *  \brief Discover a peer GATT Service.
     *
     *  \par Description:
     *       This function enables to discover a Peer GATT Service.
     *
     *  \param [in] pid
     *         Profile context ID.
     *
     *  \param [in] device
     *         Peer Device Connection Identifier.
     *
     *  \param [in] uuid
     *         Assigned UUID of this GATT Service to be looked for in remote.
     *
     *  \param [in] context
     *         Any(Optional) Upper Layer provided context for Book-keeping.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* discover_service) (GA_BRR_PRF_HANDLE, GA_BRR_DEVICE *, GA_BRR_UUID, void *);

    /**
     * Load the service information (characteristics and descriptors
     * of the specified service) and have it in the datastructure for
     * lookup during read/write.
     * - Should this have an associted service id?
     */
    /**
     *  \brief Discover composition of a given peer Service.
     *
     *  \par Description:
     *       This function enables to discover constituents of a given
     *       peer service.
     *
     *  \param [in] pid
     *         Profile context ID.
     *
     *  \param [in] device
     *         Peer Device Connection Identifier.
     *
     *  \param [in] service
     *         Service Related Information.
     *
     *  \param [in] context
     *         Any(Optional) Upper Layer provided context for Book-keeping.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* get_service_composition) (GA_BRR_PRF_HANDLE, GA_BRR_DEVICE *, GA_BRR_SVC_INFO *, void *);

    /** Write value to the specified characteristic UUID for the peer device */
    /**
     * NOTE:
     * - Should this Interface also handle Prepare Write/ Reliable Write etc?
     * - Also, Will this interface need a Char Instance associated with it
     *   esp in case of multiple instance of same char?
     */
    /**
     *  \brief Write the Characterisitc Value.
     *
     *  \par Description:
     *       This function enables to Write value of a Peer GATT Characteristic.
     *
     *  \param [in] pid
     *         Profile context ID.
     *
     *  \param [in] device
     *         Peer Device Connection Identifier.
     *
     *  \param [in] characteristic
     *         Characteristic Handle to be Read.
     *
     *  \param [in] wwr
     *         Flag to inform if Write Without Response or otherwise.
     *
     *  \param [in] context
     *         Any(Optional) Upper Layer provided context for Book-keeping.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* write_characteristic) (GA_BRR_PRF_HANDLE, GA_BRR_DEVICE *, GA_BRR_CHR_HANDLE, GA_BRR_CHR_VAL *, UINT8, void *);

    /** Read value of the specified characteristic UUID for the peer device */
    /**
     * NOTE:
     * - Should this Interface take care of handling Read Long/Blob?
     *   Else, it might need an Offset too.
     * - Also, Will this interface need a Char Instance associated with it
     *   esp in case of multiple instance of same char?
     */
    /**
     *  \brief Read the Characterisitc Value.
     *
     *  \par Description:
     *       This function enables to read value of a Peer GATT Characteristic.
     *
     *  \param [in] pid
     *         Profile context ID.
     *
     *  \param [in] device
     *         Peer Device Connection Identifier.
     *
     *  \param [in] characteristic
     *         Characteristic Handle to be Read.
     *
     *  \param [in] context
     *         Any(Optional) Upper Layer provided context for Book-keeping.
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     */
    GA_RESULT (* read_characteristic) (GA_BRR_PRF_HANDLE, GA_BRR_DEVICE *, GA_BRR_CHR_HANDLE, void *);

    /**
     * Configure notification/Indication enable/disable specified characteristic UUID for
     * the peer device.
     * NOTE:
     * - Either the state can be 0, 1, 2 or it can be TRUE/FALSE.
     *   If its the latter, then internally it should detect if its IND/NTF
     *   based on each character.
     * - Also, Will this interface need a Char Instance associated with it
     *   esp in case of multiple instance of same char?
     */

    /**
     *  \brief GA_brr_config_notification
     *
     *  \par Description
     *  This routine Configure notification/Indication enable/disable specified
     *  characteristic UUID for
     *  the peer device.
     *
     *  \param [in] pid
     *
     *  \param [in] device
     *
     *  \param [in] characteristic
     *  TODO: This needs to probably be changed to Descriptor/CCCD Handle.
     *
     *  \param [in] state
     *
     *  \param [in] context
     *
     *  \return API_SUCCESS or an error code indicating reason for failure
     *
     */
    GA_RESULT (* config_notification) (GA_BRR_PRF_HANDLE, GA_BRR_DEVICE *, GA_BRR_CHR_HANDLE, UINT8, void *);

} GA_BRR_INTERFACE;

/* --------------------------------------------- Macros */
/** Multi octet packing unpacking macros */
#define GA_PACK_LE_1_BYTE_VAL(dst, src) \
    *((UCHAR *)(dst) + 0) = (src);

#define GA_PACK_LE_2_BYTE_VAL(dst, src) \
    *((UCHAR *)(dst) + 0) = (UCHAR)(src); \
    *((UCHAR *)(dst) + 1) = (UCHAR)((src) >> 8);

#define GA_PACK_LE_3_BYTE_VAL(dst, src) \
    *((UCHAR *)(dst) + 0) = (UCHAR)(src);\
    *((UCHAR *)(dst) + 1) = (UCHAR)((src) >> 8);\
    *((UCHAR *)(dst) + 2) = (UCHAR)((src) >> 16);

#define GA_PACK_LE_4_BYTE_VAL(dst, src) \
    *((UCHAR *)(dst) + 0) = (UCHAR)(src);\
    *((UCHAR *)(dst) + 1) = (UCHAR)((src) >> 8);\
    *((UCHAR *)(dst) + 2) = (UCHAR)((src) >> 16);\
    *((UCHAR *)(dst) + 3) = (UCHAR)((src) >> 24);

#define GA_UNPACK_LE_1_BYTE(dst,src)\
    *((UCHAR *)(dst)) = (UCHAR)(*((UCHAR *)(src)));

#define GA_UNPACK_LE_2_BYTE(dst,src)\
        *((UINT16 *)(dst))  = *((src) + 1); \
        *((UINT16 *)(dst))  = *((UINT16 *)(dst)) << 8; \
        *((UINT16 *)(dst)) |= *((src) + 0);

#define GA_UNPACK_LE_3_BYTE(dst,src)\
        *((UINT32 *)(dst))  = *((src) + 2);\
        *((UINT32 *)(dst))  = (*((UINT32 *)(dst))) << 8;\
        *((UINT32 *)(dst)) |= *((src) + 1);\
        *((UINT32 *)(dst))  = (*((UINT32 *)(dst))) << 8;\
        *((UINT32 *)(dst)) |= *((src) + 0);

#define GA_UNPACK_LE_4_BYTE(dst,src)\
        *((UINT32 *)(dst))  = *((src) + 3);\
        *((UINT32 *)(dst))  = (*((UINT32 *)(dst))) << 8;\
        *((UINT32 *)(dst)) |= *((src) + 2);\
        *((UINT32 *)(dst))  = (*((UINT32 *)(dst))) << 8;\
        *((UINT32 *)(dst)) |= *((src) + 1);\
        *((UINT32 *)(dst))  = (*((UINT32 *)(dst))) << 8;\
        *((UINT32 *)(dst)) |= *((src) + 0);

#define GA_COMPARE_BRR_DEV_ADDR_TYPE(type_a,type_b)\
        (((type_a) == (type_b))?GA_TRUE:GA_FALSE)

#define GA_COMPARE_BRR_DEV_ADDR(dev_a,dev_b)\
        ((0 == GA_mem_cmp((dev_a), (dev_b), GA_BD_ADDR_SIZE))?GA_TRUE:GA_FALSE)

#define GA_COMPARE_BRR_DEVICE(dev_a,dev_b)\
        ((GA_COMPARE_BRR_DEV_ADDR_TYPE((dev_a)->bd_type,(dev_b)->bd_type)) &&\
         (GA_COMPARE_BRR_DEV_ADDR((dev_a)->bd_addr,(dev_b)->bd_addr)))

#define GA_INIT_BRR_DEVICE(dev) \
        GA_mem_set ((dev)->bd_addr, 0, GA_BD_ADDR_SIZE); \
        (dev)->bd_type = 0x00

#define GA_BRR_DEV_ADDR_IS_NON_ZERO(addr)\
        ((0x00 == (*((addr) + 0) | *((addr) + 1) | *((addr) + 2) | *((addr) + 3) | *((addr) + 4) | *((addr) + 5)))?\
        GA_FALSE:GA_TRUE)

#define GA_BRR_DEV_ADDR(dev) (dev)->bd_addr
#define GA_BRR_DEV_ADDR_TYPE(dev) (dev)->bd_type

#define GA_COPY_BRR_DEV_ADDR(dest, src) \
        BT_mem_copy ((dest), (src), GA_BD_ADDR_SIZE);

#define GA_COPY_BRR_DEV_TYPE(dest,src)\
        (dest) = (src);

#define GA_COPY_BRR_DEVICE(dest,src)\
        GA_COPY_BRR_DEV_TYPE((dest)->bd_type,(src)->bd_type)\
        GA_COPY_BRR_DEV_ADDR((dest)->bd_addr,(src)->bd_addr)

#define GA_BRR_DEVICE_FRMT_SPECIFIER\
        "ADDR: %02X:%02X:%02X:%02X:%02X:%02X, TYPE: %02X"

#define GA_BRR_DEVICE_PRINT_STR(ref)\
        (ref)->bd_addr[0],(ref)->bd_addr[1],(ref)->bd_addr[2],\
        (ref)->bd_addr[3],(ref)->bd_addr[4],(ref)->bd_addr[5],\
        (ref)->bd_type

/** Memory abstraction macros */
#define GA_mem_copy             EM_mem_copy
#define GA_mem_cmp              EM_mem_cmp
#define GA_mem_set              EM_mem_set

/* --------------------------------------------- APIs */

/**
 *  \brief To Register a BLE bearer to the GA Layer.
 *
 *  \par Description:
 *       This function enables to register the BLE bearer to GA Bearer Layer.
 *
 *  \param [in] iface
 *         The interface structure with assigned functions to different interfaces
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_register(GA_BRR_INTERFACE * iface);

/**
 *  \brief To Init the GA Bearer Layer.
 *
 *  \par Description:
 *       This function enables to inilialize the GA Bearer Layer.
 *
 *  \param [in] cb
 *         Common callback of GA core
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_init(GA_BRR_CB cb);

/**
 *  \brief To Shutdown the GA Bearer Layer.
 *
 *  \par Description:
 *       This function enables to shutdown the GA Bearer Layer.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_shutdown(void);

/**
 *  \brief Add a GATT Service.
 *
 *  \par Description:
 *       This function enables to add a GATT Service with the GA Bearer.
 *
 *  \param [in] service_uuid
 *         Assigned UUID of this GATT Service.
 *
 *  \param [in] service_type
 *         Type associated with the service.
 *
 *  \param [in] cb
 *         Callback associated with Service ID.
 *
 *  \param [out] sid
 *         Service context ID.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_add_service
          (
              /* IN  */ GA_BRR_UUID       service_uuid,
              /* IN  */ UINT8             service_type,
              /* IN  */ GA_BRR_SERVICE_CB cb,
              /* OUT */ GA_BRR_SVC_INST   * sid
          );

/**
 *  \brief Remove a GATT Service.
 *
 *  \par Description:
 *       This function enables to remove a GATT Service with the GA Bearer.
 *
 *  \param [in] sid
 *         Service context ID.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_remove_service
          (
              /* IN */ GA_BRR_SVC_INST sid
          );

/**
 *  \brief Add a Included GATT Service.
 *
 *  \par Description:
 *       This function enables to add a Included GATT Service with the
 *       GA Bearer.
 *
 *  \param [in] sid
 *         Service context ID.
 *
 *  \param [in] service_uuid
 *         Assigned UUID of this GATT Service.
 *
 *  \param [out] isid
 *         Included Service context ID.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_include_service
          (
              /* IN  */ GA_BRR_SVC_INST sid,
              /* IN  */ GA_BRR_UUID     service_uuid,
              /* OUT */ GA_BRR_SVC_INST * isid
          );

/**
 *  \brief Add a GATT Characteristic to a Service.
 *
 *  \par Description:
 *       This function enables to add a GATT Characteristic to a given
 *       Service with the GA Bearer.
 *
 *  \param [in] sid
 *         Service context ID.
 *
 *  \param [in] char_uuid
 *         Assigned UUID of this GATT Characteristic.
 *
 *  \param [in] char_property
 *         Properties associated with this GATT Characteristic.
 *
 *  \param [in] value
 *         Any value associated with this GATT Characteristic.
 *
 *  \param [out] cid
 *         Characteristic context ID.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_add_characteristic
          (
              /* IN  */ GA_BRR_SVC_INST sid,
              /* IN  */ GA_BRR_UUID     char_uuid,
              /* IN  */ UINT8           char_property,
              /* IN  */ GA_BRR_CHR_VAL  * value,
              /* OUT */ GA_BRR_CHR_INST * cid
          );

/**
 * Provision to update the characteric value
 */
/**
 *  \brief Update a GATT Characteristic to a Service.
 *
 *  \par Description:
 *       This function enables to Update a GATT Characteristic to a given
 *       Service with the GA Bearer.
 *
 *  \param [in] sid
 *         Service context ID.
 *
 *  \param [in] char_uuid
 *         Assigned UUID of this GATT Characteristic.
 *
 *  \param [in] cid
 *         Characteristic context ID.
 *
 *  \param [in] value
 *         Any value associated with this GATT Characteristic.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_update_characteristic_value
          (
              /* IN */ GA_BRR_SVC_INST sid,
              /* IN */ GA_BRR_UUID     char_uuid,
              /* IN */ GA_BRR_CHR_INST cid,
              /* IN */ GA_BRR_CHR_VAL  * value
          );

/**
 *  \brief Send response for a Characterisitc Write.
 *
 *  \par Description:
 *       This function enables to respond to a Characteritis Write
 *       from a peer device.
 *
 *  \param [in] device
 *         Peer Device Connection Identifier.
 *
 *  \param [in] ctx
 *         Assigned UUID of this GATT Characteristic.
 *
 *  \param [in] status
 *         Characteristic context ID.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_write_characteristic_rsp
          (
              /* IN */ GA_BRR_DEVICE      * device,
              /* IN */ GA_BRR_CHR_CONTEXT * ctx,
              /* IN */ UINT16             status
          );

/**
 *  \brief Send response for a Characterisitc Read.
 *
 *  \par Description:
 *       This function enables to respond to a Characteritis Read
 *       from a peer device.
 *
 *  \param [in] device
 *         Peer Device Connection Identifier.
 *
 *  \param [in] ctx
 *         Assigned UUID of this GATT Characteristic.
 *
 *  \param [in] status
 *         Characteristic context ID.
 *
 *  \param [in] value
 *         Any value associated with this GATT Characteristic.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_read_characteristic_rsp
          (
              /* IN */ GA_BRR_DEVICE      * device,
              /* IN */ GA_BRR_CHR_CONTEXT * ctx,
              /* IN */ UINT16             status,
              /* IN */ GA_BRR_CHR_VAL     * value
          );

/** Notify/Indicate value of the specified characteristic UUID for the peer device */
/**
 *  \brief Notify a Characterisitic Value to peer device.
 *
 *  \par Description:
 *       This function enables to send a charactertisic Notifications to
 *       peer device.
 *
 *  \param [in] device
 *         Peer Device Connection Identifier.
 *
 *  \param [in] sid
 *         Service context ID.
 *
 *  \param [in] char_uuid
 *         Assigned UUID of this GATT Characteristic.
 *
 *  \param [in] cid
 *         Characteristic context ID where needed, else can be
 *         \ref GA_BRR_INST_DONTCARE.
 *
 *  \param [in] value
 *         Any value associated with this GATT Characteristic.
 *
 *  \param [in] nwr
 *         TODO: Check what this is!
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_notify_characteristic
          (
              /* IN */ GA_BRR_DEVICE   * device,
              /* IN */ GA_BRR_SVC_INST sid,
              /* IN */ GA_BRR_UUID     char_uuid,
              /* IN */ GA_BRR_CHR_INST cid,
              /* IN */ GA_BRR_CHR_VAL  * value,
              /* IN */ UINT8           nwr
          );

/**
 * Register a profile callback from GA and assign a profile ID for further
 * referencing.
 * Assign a profile ID or Profile ID gets assigned internally and comes
 * as Out?
 */
/**
 *  \brief Register a profile client/collector.
 *
 *  \par Description:
 *       This function enables to Register a profile client/collector module
 *       with the GA Bearer.
 *
 *  \param [in] cb
 *         Profile Callback.
 *
 *  \param [out] pid
 *         Profile context ID.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_register_profile
          (
              /* IN  */ GA_BRR_PROFILE_CB  cb,
              /* OUT */ GA_BRR_PRF_HANDLE * pid
          );

/**
 *  \brief To Unregister a GA Profile with GA Bearer.
 *
 *  \par Description:
 *       This function enables to unregister a profile with GA Bearer.
 *
 *  \param [in] pid
 *         Profile context ID.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_unregister_profile
          (
              /* IN */ GA_BRR_PRF_HANDLE pid
          );


/**
 * Enhance the bearer transport if required by the profile or application - eATT
 * Should the needed MTU(or other associated things incase of eATT) also be
 * part of this interface? Else, we might need some other interface for that.
 */
/**
 *  \brief Update or Setup a new Transport.
 *
 *  \par Description:
 *       TODO: Need to revist for both Profile and Server roles.
 *
 *  \param [in] pid
 *         Profile context ID.
 *
 *  \param [in] type
 *         Type of Transport.
 *
 *  \param [in] enable
 *         State of Transport.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_setup_transport
          (
              /* IN */ GA_BRR_PRF_HANDLE pid,
              /* IN */ UINT8             type,
              /* IN */ UINT8             enable
          );

/**
 * Discover the service information from a profile instance for a service from
 * the peer device.
 */
/**
 *  \brief Discover a peer GATT Service.
 *
 *  \par Description:
 *       This function enables to discover a Peer GATT Service.
 *
 *  \param [in] pid
 *         Profile context ID.
 *
 *  \param [in] device
 *         Peer Device Connection Identifier.
 *
 *  \param [in] uuid
 *         Assigned UUID of this GATT Service to be looked for in remote.
 *
 *  \param [in] context
 *         Any(Optional) Upper Layer provided context for Book-keeping.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_discover_service
          (
              /* IN */ GA_BRR_PRF_HANDLE pid,
              /* IN */ GA_BRR_DEVICE     * device,
              /* IN */ GA_BRR_UUID       uuid,
              /* IN */ void              * context
          );

/**
 * Load the service information (characteristics and descriptors
 * of the specified service) and have it in the datastructure for
 * lookup during read/write.
 * - Should this have an associted service id?
 */
/**
 *  \brief Discover composition of a given peer Service.
 *
 *  \par Description:
 *       This function enables to discover constituents of a given
 *       peer service.
 *
 *  \param [in] pid
 *         Profile context ID.
 *
 *  \param [in] device
 *         Peer Device Connection Identifier.
 *
 *  \param [in] service
 *         Service Related Information.
 *
 *  \param [in] context
 *         Any(Optional) Upper Layer provided context for Book-keeping.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_get_service_composition
          (
              /* IN */ GA_BRR_PRF_HANDLE pid,
              /* IN */ GA_BRR_DEVICE     * device,
              /* IN */ GA_BRR_SVC_INFO   * service,
              /* IN */ void              * context
          );

/** Write value to the specified characteristic UUID for the peer device */
/**
 * NOTE:
 * - Should this Interface also handle Prepare Write/ Reliable Write etc?
 * - Also, Will this interface need a Char Instance associated with it
 *   esp in case of multiple instance of same char?
 */
/**
 *  \brief Write the Characterisitc Value.
 *
 *  \par Description:
 *       This function enables to Write value of a Peer GATT Characteristic.
 *
 *  \param [in] pid
 *         Profile context ID.
 *
 *  \param [in] device
 *         Peer Device Connection Identifier.
 *
 *  \param [in] characteristic
 *         Characteristic Handle to be Read.
 *
 *  \param [in] wwr
 *         Flag to inform if Write Without Response or otherwise.
 *
 *  \param [in] context
 *         Any(Optional) Upper Layer provided context for Book-keeping.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_write_characteristic
          (
              /* IN */ GA_BRR_PRF_HANDLE pid,
              /* IN */ GA_BRR_DEVICE     * device,
              /* IN */ GA_BRR_CHR_HANDLE characteristic,
              /* IN */ GA_BRR_CHR_VAL    * value,
              /* IN */ UINT8             wwr,
              /* IN */ void              * context
          );

/** Read value of the specified characteristic UUID for the peer device */
/**
 * NOTE:
 * - Should this Interface take care of handling Read Long/Blob?
 *   Else, it might need an Offset too.
 * - Also, Will this interface need a Char Instance associated with it
 *   esp in case of multiple instance of same char?
 */
/**
 *  \brief Read the Characterisitc Value.
 *
 *  \par Description:
 *       This function enables to read value of a Peer GATT Characteristic.
 *
 *  \param [in] pid
 *         Profile context ID.
 *
 *  \param [in] device
 *         Peer Device Connection Identifier.
 *
 *  \param [in] characteristic
 *         Characteristic Handle to be Read.
 *
 *  \param [in] context
 *         Any(Optional) Upper Layer provided context for Book-keeping.
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 */
GA_RESULT GA_brr_read_characteristic
          (
              /* IN */ GA_BRR_PRF_HANDLE pid,
              /* IN */ GA_BRR_DEVICE     * device,
              /* IN */ GA_BRR_CHR_HANDLE characteristic,
              /* IN */ void              * context
          );

/**
 * Configure notification/Indication enable/disable specified characteristic UUID for
 * the peer device.
 * NOTE:
 * - Either the state can be 0, 1, 2 or it can be TRUE/FALSE.
 *   If its the latter, then internally it should detect if its IND/NTF
 *   based on each character.
 * - Also, Will this interface need a Char Instance associated with it
 *   esp in case of multiple instance of same char?
 */

/**
 *  \brief GA_brr_config_notification
 *
 *  \par Description
 *  This routine Configure notification/Indication enable/disable specified
 *  characteristic UUID for
 *  the peer device.
 *
 *  \param [in] pid
 *
 *  \param [in] device
 *
 *  \param [in] characteristic
 *  TODO: This needs to probably be changed to Descriptor/CCCD Handle.
 *
 *  \param [in] state
 *
 *  \param [in] context
 *
 *  \return API_SUCCESS or an error code indicating reason for failure
 *
 */
GA_RESULT GA_brr_config_notification
          (
              /* IN */ GA_BRR_PRF_HANDLE pid,
              /* IN */ GA_BRR_DEVICE     * device,
              /* IN */ GA_BRR_CHR_HANDLE characteristic,
              /* IN */ UINT8             state,
              /* IN */ void              * context
          );

#endif /* _H_GA_BEARER_API_ */

